import java.util.Arrays;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;

/**
 * 操作数组的工具类：Arrays
 * 编译：javac -encoding UTF-8 ArraysTest.java
 * 运行：java ArraysTest
 */
public class ArraysTest {
    /**
     * Java提供的Arrays类里包含的一些static修饰的方法可以直接操作数组，
     * 这个Arrays类里包含了如下几个static修饰的方法（static修饰的方法可以直接通过类名调用）。
     * <p>
     * ➢ int binarySearch(type[] a, type key)：使用二分法查询key元素值在a数组中出现的索引；如果a数组不包含key元素值，则返回负数。调用该方法时要求数组中元素已经按升序排列，这样才能得到正确结果。
     * ➢ int binarySearch(type[] a, int fromIndex, inttoIndex, type key)：这个方法与前一个方法类似，但它只搜索a数组中fromIndex到toIndex索引的元素。调用该方法时要求数组中元素已经按升序排列，这样才能得到正确结果。
     * ➢ type[] copyOf(type[] original, int length)：这个方法将会把original数组复制成一个新数组，其中length是新数组的长度。
     * 如果length小于original数组的长度，则新数组就是原数组的前面length个元素；
     * 如果length大于original数组的长度，则新数组的前面元素就是原数组的所有元素，后面补充0（数值类型）、false（布尔类型）或者null（引用类型）。
     * ➢ type[] copyOfRange(type[] original, int from,int to)：这个方法与前面方法相似，但这个方法只复制original数组的from索引到to索引的元素。
     * ➢ boolean equals(type[] a, type[] a2)：如果a数组和a2数组的长度相等，而且a数组和a2数组的数组元素也一一相同，该方法将返回true。
     * ➢ void fill(type[] a, type val)：该方法将会把a数组的所有元素都赋值为val。
     * ➢ void fill(type[] a, int fromIndex, int toIndex,type val)：该方法与前一个方法的作用相同，区别只是该方法仅仅将a数组的fromIndex到toIndex索引的数组元素赋值为val。
     * ➢ void sort(type[] a)：该方法对a数组的数组元素进行排序。
     * ➢ void sort(type[] a, int fromIndex, int toIndex)：该方法与前一个方法相似，区别是该方法仅仅对fromIndex到toIndex索引的元素进行排序。
     * ➢ String toString(type[] a)：该方法将一个数组转换成一个字符串。该方法按顺序把多个数组元素连缀在一起，多个数组元素使用英文逗号（,）和空格隔开。
     */
    public static void ArraysTest1() {
        int[] a1 = new int[]{3, 4, 5, 6};
        int[] a2 = new int[]{3, 4, 5, 6};
        // 两个数组长度相等，每个元素依次相等，将输出true
        System.out.println("a1数组和a2数组是否相等：" + Arrays.equals(a1, a2));
        // 通过复制a1数组，生成一个新的b数组
        int[] b = Arrays.copyOf(a1, 6);
        System.out.println("a1数组和b数组是否相等：" + Arrays.equals(a1, b));
        // 输出b数组的元素，将输出 [3, 4, 5, 6, 0, 0]
        System.out.println("b数组的元素为：" + Arrays.toString(b));
        // 将b数组的第3个元素（包含）到第5个元素（不包含）赋值为1
        Arrays.fill(b, 2, 4, 1);
        // 输出b数组的元素，将输出 [3, 4, 1, 1, 0, 0]
        System.out.println("b数组的元素为：" + Arrays.toString(b));
        // 对数组b进行排序
        Arrays.sort(b);
        // 输出b数组的元素，将输出 [0, 0, 1, 1, 3, 4]
        System.out.println("b数组的元素为：" + Arrays.toString(b));
        /*
         * 除此之外，在System类里也包含了一个arraycopy方法，
         * static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
         * 该方法可以将src数组里的元素值赋给dest数组的元素，
         * 其中srcPos指定从src数组的第几个元素开始赋值，
         * length参数指定将src数组的多少个元素值赋给dest数组的元素。
         */
    }

    /**
     * Java 8增强了Arrays类的功能，为Arrays类增加了一些工具方法，
     * 这些工具方法可以充分利用多CPU并行的能力来提高设值、排序的性能。
     * 下面是Java 8为Arrays类增加的工具方法。
     * <p>
     * ➢ void parallelPrefix(xxx[] array,XxxBinaryOperator op)：该方法使用op参数指定的计算公式计算得到的结果作为新的数组元素。op计算公式包括left、right两个形参，
     * 其中left代表新数组中前一个索引处的元素，right代表array数组中当前索引处的元素。新数组的第一个元素无须计算，直接等于array数组的第一个元素。
     * ➢ void parallelPrefix(xxx[] array, int fromIndex,int toIndex, XxxBinaryOperator op)：该方法与上一个方法相似，区别是该方法仅重新计算fromIndex到toIndex索引的元素。
     * ➢ void setAll(xxx[] array, IntToXxxFunctiongenerator)：该方法使用指定的生成器（generator）为所有数组元素设置值，该生成器控制数组元素的值的生成算法。
     * ➢ void parallelSetAll(xxx[] array,IntToXxxFunction generator)：该方法的功能与上一个方法相同，只是该方法增加了并行能力，可以利用多CPU并行来提高性能。
     * ➢ void parallelSort(xxx[] a)：该方法的功能与Arrays类以前就有的sort()方法相似，只是该方法增加了并行能力，可以利用多CPU并行来提高性能。
     * ➢ void parallelSort(xxx[] a, int fromIndex, inttoIndex)：该方法与上一个方法相似，区别是该方法仅对fromIndex到toIndex索引的元素进行排序。
     * ➢ Spliterator.OfXxx spliterator(xxx[] array)：将该数组的所有元素转换成对应的Spliterator对象。
     * ➢ Spliterator.OfXxx spliterator(xxx[] array, intstartInclusive, int endExclusive)：该方法与上一个方法相似，区别是该方法仅转换startInclusive到endExclusive索引的元素。
     * ➢ XxxStream stream(xxx[] array)：该方法将数组转换为Stream，Stream是Java 8新增的流式编程的API。
     * ➢ XxxStream stream(xxx[] array, int startInclusive,int endExclusive)：该方法与上一个方法相似，区别是该方法仅将fromIndex到toIndex索引的元素转换为Stream。
     * 上面方法列表中，所有以parallel开头的方法都表示该方法可利用CPU并行的能力来提高性能。上面方法中的xxx代表不同的数据类型，比如处理int[]型数组时应将xxx换成int，处理long[]型数组时应将xxx换成long。
     */
    public static void ArraysTest2() {
        int[] arr1 = new int[]{3, -4, 25, 16, 30, 18};
        // 对数组arr1进行并发排序
        Arrays.parallelSort(arr1);  // 该方法的功能与传统sort()方法大致相似，只是在多CPU机器上会有更好的性能。
        System.out.println(Arrays.toString(arr1));

        // 通过特定的算法修改arr2每个元素的值
        int[] arr2 = new int[]{3, -4, 25, 16, 30, 18};
        Arrays.parallelPrefix(arr2, new IntBinaryOperator() {
            /**
             *
             * @param left 新数组中前一个索引处的元素
             * @param right 原数组中当前索引处的元素
             * @return 元素的新值
             */
            @Override
            public int applyAsInt(int left, int right) {
                return left * right;
            }
        });
        System.out.println(Arrays.toString(arr2));

        int[] arr3 = new int[5];
        Arrays.parallelSetAll(arr3, new IntUnaryOperator() {
            /**
             *
             * @param operand 正则计算的元素索引
             * @return 元素的新值
             */
            @Override
            public int applyAsInt(int operand) {
                return operand * 5;
            }
        });
        System.out.println(Arrays.toString(arr3));
    }

    public static void main(String[] args) {
        ArraysTest1();
        ArraysTest2();
    }
}
